<template>
  <div>
    <n-card :bordered="false" title='请选择数据表'>
      <n-form
        inline
        :model='tableForm'
        label-placement="left"
      >
        <n-grid :cols="24" :x-gap="40">
          <n-form-item-gi :span="6" path='tableName'>
            <n-select
              v-model:value="tableForm.tableName"
              :options="tableOption"
              @update:value="changeTable"></n-select>
          </n-form-item-gi>
        
          <n-form-item-gi :span="10">
            <n-space>
              <n-button @click="getTableInfo" :loading="loadingTable" type='info'>获取表信息</n-button>
              <n-button @click="generateCode" v-show="showDetail" :loading="saving" type='primary'>保存代码</n-button>
            </n-space>
          </n-form-item-gi>
        </n-grid>
      </n-form>
    </n-card>

    
    <div v-if='showDetail'>
      <!-- 数据表基本信息 -->
      <n-card :bordered="false" class='mt15' title='基本信息'>
        <n-form
          :label-width='100'
          :model='generateInfo'
          label-placement="left"
        >
          <n-grid :cols="24" :x-gap="40">
            <n-form-item-gi :span="10" label='代码生成路径' path='path'>
              <n-input v-model:value="generateInfo.path" placeholder="请输入名称" />
            </n-form-item-gi>
          </n-grid>
          <n-grid :cols="24" :x-gap="40">
            <n-form-item-gi :span="10" label='JavaBean类名' path='beanName'>
              <n-input v-model:value="generateInfo.beanName" placeholder="请输入名称" />
            </n-form-item-gi>
            <n-form-item-gi :span="10" label='JavaBean包名' path='beanPackageName'>
              <n-input v-model:value="generateInfo.beanPackageName" placeholder="请输入名称" />
            </n-form-item-gi>
            <n-form-item-gi :span="10" label='Dao接口名' path='daoName'>
              <n-input v-model:value="generateInfo.daoName" placeholder="请输入名称" />
            </n-form-item-gi>
            <n-form-item-gi :span="10" label='Dao包名' path='daoPackageName'>
              <n-input v-model:value="generateInfo.daoPackageName" placeholder="请输入名称" />
            </n-form-item-gi>
            <n-form-item-gi :span="10" label='Controller类名' path='controllerName'>
              <n-input v-model:value="generateInfo.controllerName" placeholder="请输入名称" />
            </n-form-item-gi>
            <n-form-item-gi :span="10" label='Controller包名' path='controllerPackageName'>
              <n-input v-model:value="generateInfo.controllerPackageName" placeholder="请输入名称" />
            </n-form-item-gi>
          </n-grid>
        </n-form>
      </n-card>

      <!-- 数据表字段详情 -->
      <n-card :bordered="false" class='mt15' title='字段详情'>
        <n-data-table
          :columns='columns'
          :data='tableDetailList'
        >
        </n-data-table>
      </n-card>

    </div>
  </div>
</template>

<script lang="ts" setup>
  import { onMounted, ref, unref, reactive, getCurrentInstance, computed, h } from 'vue'
  import { getTables, getTableField, saveCode } from '@/api/tool/generate'
  import { NButton, NInput, NSpace } from 'naive-ui'

  const internalInstance = getCurrentInstance()
  const { $message } = internalInstance?.appContext.config.globalProperties
  const tableForm = ref({
    tableName: ''
  })
  const tableOption = ref([])

  /** 选择数据表时 */
  function changeTable() {
    getTableInfo()
  }

  const basePackage = ref('com.sunxueqi.')
  const loadingTable = ref(false)
  const showDetail = ref(false)
  const saving = ref(false)
  const tableDetailList = ref([])
  const columns = [
    {
      title: '表字段名',
      key: 'columnName',
      width: 120
    }, {
      title: '表字段类型',
      key: 'columnType',
      width: 120
    }, {
      title: '字段描述',
      key: 'columnComment',
      width: 120,
      render: function(row: any) {
        if(row.edit) {
          return h(
            NInput,
            {
              value: row.columnComment,
              onUpdateValue: (value) => changeValue(row, 'columnComment', value)
            }
          )
        } else {
          return row.columnComment
        }
      }
    }, {
      title: 'Java类属性名',
      key: 'name',
      width: 120,
      render: function(row: any) {
        if(row.edit) {
          return h(
            NInput,
            {
              value: row.name,
              onUpdateValue: (value) => changeValue(row, 'name', value)
            }
          )
        } else {
          return row.name
        }
      }
    }, {
      title: 'Java类字段类型',
      key: 'type',
      width: 120,
      render: function(row: any) {
        if(row.edit) {
          return h(
            NInput,
            {
              value: row.type,
              onUpdateValue: (value) => changeValue(row, 'type', value)
            }
          )
        } else {
          return row.type
        }
      }
    }, {
      title: '默认值',
      key: 'columnDefault',
      width: 120,
      render: function(row: any) {
        if(row.edit) {
          return h(
            NInput,
            {
              value: row.columnDefault,
              onUpdateValue: (value) => changeValue(row, 'columnDefault', value)
            }
          )
        } else {
          return row.columnDefault
        }
      }
    }, {
      title: '操作',
      key: 'operate',
      width: 160,
      align: 'center',
      render: function(row: any) {
        if(row.edit) {
          return h(
            NSpace,
            {
              justify: "center"
            },
            [
              h(
                NButton,
                { size: 'small', type: 'primary', onClick: () => cancel(row) },
                { default: () => '保存' }
              ),
              h(
                NButton,
                { size: 'small', onClick: () => cancel(row) },
                { default: () => '取消' }
              )
            ]
          )
        } else {
          return h(
            NButton,
            {
              size: 'small',
              type: 'info',
              onClick: () => editRow(row)
            },
            { default: () => '编辑' }
          )
        }
      }
    }
  ]

  function getTableInfo() {
    if(!tableForm.value.tableName) {
      $message.warning('请选择数据表')
      return false
    }
    loadingTable.value = true
    getTableField(unref(tableForm).tableName).then(res => {
      showDetail.value = true

      const list = res.data.fields
      tableDetailList.value = list.map((item:any) => {
        item.edit = false
        item.originName = item.name
        item.originType = item.type
        item.originColumnComment = item.columnComment
        item.originColumnDefault = item.columnDefault
        return item
      });

      const beanName = res.data.beanName
      generateInfo.value.beanName = beanName
      generateInfo.value.daoName = beanName + 'Mapper'
      generateInfo.value.controllerName = beanName + 'Controller'
      generateInfo.value.beanPackageName = basePackage.value + beanName.toLowerCase() + '.vo'
      generateInfo.value.daoPackageName = basePackage.value + beanName.toLowerCase() + '.dao'
      generateInfo.value.controllerPackageName = basePackage.value + beanName.toLowerCase() + '.controller'

      loadingTable.value = false
    })
  }

  function generateCode() {
    saving.value = true
    const data: any = generateInfo.value
    data['tableDetail'] = tableDetailList
    data['tableName'] = tableForm.value.tableName
    
    saveCode(data).then(res => {
      $message.success('代码生成成功')
    }).catch(e => {
      $message.error('代码生成失败')
    }).finally(() => {
      saving.value = false
    })
  }

  const generateInfo = ref({
    path: 'D:/generate1',
    beanName: '',
    daoName: '',
    controllerName: '',
    beanPackageName: '',
    daoPackageName: '',
    controllerPackageName: ''
  })

  function editRow(row: any) {
    row.edit = true
  }

  function cancel(row: any) {
    row.edit = false
  }

  function changeValue(row: any, field: any, e: any) {
    const list: any = tableDetailList.value
    list.forEach((item: any, index: number) => {
      if(item.columnName === row.columnName) {
        list[index][field] = e
      }
    })
  }

  onMounted(() => {
    getTables().then(res => {
      tableOption.value = res.data.tableName.map((item: any) => {
        return {
          label: item,
          value: item
        }
      })

    })
  })
</script>